package com.wayne.cas.login;

import com.wayne.cas.constant.ContextConstant;
import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler;
import org.apereo.cas.authentication.AuthenticationHandlerExecutionResult;
import org.apereo.cas.authentication.Credential;
import org.apereo.cas.authentication.PreventedException;
import org.apereo.cas.authentication.principal.PrincipalFactory;
import org.apereo.cas.services.ServicesManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.security.auth.login.FailedLoginException;
import javax.servlet.http.HttpSession;
import javax.sql.DataSource;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class UsernamePasswordKaptchaAuthenticationHandler extends QueryDatabaseAuthenticationHandler {
  Logger log = LoggerFactory.getLogger(UsernamePasswordKaptchaAuthenticationHandler.class);

  public UsernamePasswordKaptchaAuthenticationHandler(String name, ServicesManager servicesManager, PrincipalFactory principalFactory, Integer order, DataSource dataSource, String sql, String fieldPassword, String fieldExpired, String fieldDisabled, Map<String, Object> attributes) {
    super(name, servicesManager, principalFactory, order, dataSource, sql, fieldPassword, fieldExpired, fieldDisabled, attributes);
  }

  @Override
  public boolean supports(Credential credential) {
    //判断传递过来的Credential 是否是自己能处理的类型
    return credential instanceof UsernamePasswordKaptchaCredential;
  }

  @Override
  protected AuthenticationHandlerExecutionResult doAuthentication(Credential credential) throws GeneralSecurityException, PreventedException {
    UsernamePasswordKaptchaCredential thisCredential = (UsernamePasswordKaptchaCredential) credential;
    String kaptcha = thisCredential.getKaptcha();
    //从Session中读取验证码
    String vCode;
    try {
      HttpSession httpSession = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getSession();
      Object object = httpSession.getAttribute(ContextConstant.VALIDATE_CODE_KEY);
      httpSession.removeAttribute(ContextConstant.VALIDATE_CODE_KEY);
      vCode = null == object ? null : object.toString();
    } catch (Exception e) {
      throw new FailedLoginException("无法获取验证码");
    }
    log.info("++{}, {} =========================", kaptcha, vCode);
    //比对验证码
    if (StringUtils.isNotBlank(kaptcha)
        && kaptcha.equals(vCode)) {
      super.doAuthentication(credential);
      return createHandlerResult(
          thisCredential,
          principalFactory.createPrincipal(thisCredential.getUsername(), new HashMap<>()),
          new ArrayList<>()
      );
    }
    throw new FailedLoginException("验证码错误");
  }

}